package com.yzpass.api.user.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yzpass.api.common.FilterDTO;
import com.yzpass.api.common.OffsetPage;
import com.yzpass.api.common.Result;
import com.yzpass.api.common.cache.ICache;
import com.yzpass.api.common.util.RandomUtil;
import com.yzpass.api.security.UserPermissionService;
import com.yzpass.api.user.dto.UserDTO;
import com.yzpass.api.user.dto.UserPassResetDTO;
import com.yzpass.api.user.entity.User;
import com.yzpass.api.user.entity.UserRole;
import com.yzpass.api.user.mapper.UserMapper;
import com.yzpass.api.user.mapper.UserRoleMapper;
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Service
public class UserService {

    @Resource
    UserMapper userMapper;

    @Resource
    UserRoleMapper userRoleMapper;

    @Resource
    LoginService loginService;

    @Resource
    ICache iCache;

    @Resource
    UserPermissionService userPermissionService;

    public Result<List<UserDTO>> list(@RequestBody FilterDTO input)  {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        if(StringUtils.isNotBlank(input.getKeyword())){
            String keyword = input.getKeyword();
            queryWrapper.nested(c-> c.like(User::getUsername,keyword)
                    .or().like(User::getName,keyword)
                    .or().like(User::getEmail,keyword));
        }

        queryWrapper.orderByDesc(User::getCreateTime);
        OffsetPage<User> p = new OffsetPage<>(input.getOffset(),input.getSize());
        IPage<User> iPage =  userMapper.selectPage(p,queryWrapper);
        List<UserDTO> list = iPage.getRecords().stream().map(UserDTO::fromUser).toList();
        return Result.success(list,iPage.getTotal());
    }

    public Result delete(String id) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUserId,UUID.fromString(id));
        userMapper.delete(queryWrapper);
        return Result.success();
    }

    @Transactional
    public Result<UserDTO> save(UserDTO input) {
        User dbUser = userMapper.selectById(input.getUserId());
        User inputUser = input.toUser();
        iCache.remove(userPermissionService.userRoleKey(inputUser.getUserId()));
        if(dbUser==null){
            userMapper.insert(inputUser);
        }else{
            userMapper.updateById(inputUser);
        }
        var wrapper = new LambdaQueryWrapper<UserRole>();
        wrapper.eq(UserRole::getUserId,inputUser.getUserId());
        userRoleMapper.delete(wrapper);

        if(input.getRoleIds()!=null && !input.getRoleIds().isEmpty()){
            List<UserRole> list = new ArrayList<>();
            for(String str:input.getRoleIds()){
                UserRole userRole = new UserRole();
                userRole.setUserId(inputUser.getUserId());
                userRole.setRoleId(UUID.fromString(str));
                list.add(userRole);
            }
            userRoleMapper.insert(list);
        }

        return view(input.getUserId());
    }

    public Result<UserDTO> view(String id) {
        User user = userMapper.selectById(id);
        UserDTO dto = UserDTO.fromUser(user);

        var wrapper = new LambdaQueryWrapper<UserRole>();
        wrapper.eq(UserRole::getUserId,UUID.fromString(id));
        List<UserRole> userRoles = userRoleMapper.selectList(wrapper);
        List<String> roleIds = userRoles.stream().map(t->t.getRoleId().toString()).toList();
        dto.setRoleIds(roleIds);

        return Result.success(dto);
    }

    public Result<UserPassResetDTO> passReset(String id) {
        User user = userMapper.selectById(id);
        if(user==null){
            return Result.error("未找到用户");
        }
        var dto = UserPassResetDTO.fromUser(user);
        String salt = RandomUtil.generateRandomString(8);
        String pass = RandomUtil.generateRandomString(16);
        user.setSalt(salt);
        user.setPassword(loginService.encrypt(pass,salt));
        userMapper.updateById(user);
        dto.setPassword(pass);
        return Result.success(dto);
    }

}
